#pragma once

#ifndef _MFUNCT_H
#define _MFUNCT_H

/*
	There are so many way to express a math symbol, here I prefer
	my own way (you can make a change to suit your wish).

	This is used to define math symbols and operator.
	If it's a function that maybe has a sub-function like sin(x+a)...
	so it has two term, an open term and a close term
	ex: sin( and sin)
	
	Modified by Dao Anh Vu on Dec 16, 2010
*/

#define SIN     1
#define COS     2
#define TAN     3
#define COTAN	4
#define LN 		5
#define LOG		6
#define POW  	7
#define OPENP 	8 /* open parentheses */
#define CLOSEP 	9 /* close parentheses */


#define VAL			10
#define OPERATOR	20
#define FUN			30
#define VAR			40

#define DIV0		10



typedef struct tagPostfixNode
{
	double value;
	char operator;
	
	//1: value
	//2: operator +,-,*,/
	//3: sin(, sin), cos(, cos), tan(, tan) ,(,),^(, ^), ln(, ln)
	//4: varible
	unsigned char type;
	unsigned char priority;
	
    struct tagPostfixNode *next;
    struct tagPostfixNode *before;

} POSTFIX, *PPOSTFIX;

typedef struct tagFunction
{
	char *formula;
	int iLen;
	char isNormalized, isErr;
	PPOSTFIX pPostfix;

	char parameter[5];
	int paramlen;
} MFunction;


PPOSTFIX pop(PPOSTFIX *stack);
void push(PPOSTFIX *stack, PPOSTFIX p);
void releaseStack(PPOSTFIX *);
int countNode(PPOSTFIX stack);
void releaseStack(PPOSTFIX *stack);
void addTail(PPOSTFIX *st, PPOSTFIX p);

int normalize(MFunction *f);
void toPostfix();
void initFunction(MFunction *f);
void init(PPOSTFIX *);
MFunction *createFunction(char *f, int len);
void setFunction(char *str, int len, MFunction *f);
void releaseFunction(MFunction *);


int validateFormula(char *f);

//these function use Reserve Polish Notation(RPN) algorithm
//to calculate value of formula/ function at position x
double calculate(MFunction *f, float x);

double parseDoubleWithError(char *s, int len, char *error);
double parseDouble(char *s, int len, int *start);
double doCalculate(double operand1, double operand2, unsigned char operator, char *error);
double doCalculateBasicUnaryFunction(double x, char f);

#endif
